home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Tools - Objects / MacApp / MacApp CD Release / MacApp 2.0.1 (Hard Disk Ready) / Examples / DrawShapes / UMenu.inc1.p < prev    next >
Encoding:
Text File  |  1990-10-25  |  14.5 KB  |  654 lines  |  [TEXT/MPS ]

  1. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  2.  
  3. TYPE
  4.     MenuRec             = RECORD
  5.         mID:                INTEGER;
  6.         mObject:            TMenu;
  7.         END;
  8.     MenuArray            = ARRAY [1..4000] OF MenuRec;
  9.     MenuArrayPtr        = ^MenuArray;
  10.     MenuArrayHandle     = ^MenuArrayPtr;
  11.  
  12. VAR
  13.     pMenuCPort:         CGrafPort;                        { Color port for compatibility. }
  14.                                                         { Private grafPort used to focus the menu w/o
  15.                                                          messing up the Window Manager port. }
  16.     pMenuArray:         MenuArrayHandle;                { Used to find the TMenu given a MenuHandle.
  17.                                                          }
  18.     pNumMenus:            INTEGER;
  19.  
  20.     pCustDefproc:        Handle;                         { Replaces the menu's menuProc field }
  21.  
  22. {--------------------------------------------------------------------------------------------------}
  23.     { Returns the TickCount some time in the future. }
  24.  
  25. FUNCTION Future(delta: LONGINT): LONGINT;
  26.  
  27.     BEGIN
  28.     Future := TickCount + delta;
  29.     END;
  30.  
  31. {--------------------------------------------------------------------------------------------------}
  32.  
  33. {$S ARes}
  34.  
  35. PROCEDURE WaitTickChange;
  36.  
  37.     VAR
  38.         now:                LONGINT;
  39.  
  40.     BEGIN
  41.     now := TickCount;
  42.     REPEAT
  43.     UNTIL TickCount <> now;
  44.     END;
  45.  
  46. {--------------------------------------------------------------------------------------------------}
  47.  
  48. {$S ARes}
  49.  
  50. FUNCTION FindTMenu(theMenu: MenuHandle): TMenu;
  51.  
  52.     VAR
  53.         i:                    INTEGER;
  54.         p:                    MenuArrayPtr;
  55.         id:                 INTEGER;
  56.  
  57.     BEGIN
  58.     FindTMenu := NIL;
  59.     p := pMenuArray^;
  60.     id := theMenu^^.menuID;
  61.  
  62.     FOR i := 1 TO pNumMenus DO
  63.         WITH p^[i] DO
  64.             IF mID = id THEN
  65.                 BEGIN
  66.                 FindTMenu := mObject;
  67.                 Exit(FindTMenu);
  68.                 END;
  69.     END;
  70.  
  71. {--------------------------------------------------------------------------------------------------}
  72. { Called by the MDEF resource. }
  73. {$Push} {$IFC qTrace} {$D+} {$ENDC}
  74.  
  75. {$S ARes}
  76.  
  77. PROCEDURE MenuDefproc(message: INTEGER;
  78.                       theMenu: MenuHandle;
  79.                       VAR menuRect: Rect;
  80.                       hitPt: Point;
  81.                       VAR whichItem: INTEGER);
  82.  
  83.     VAR
  84.         menuObj:            TMenu;
  85.         OldA5:                Longint;
  86.  
  87.     BEGIN
  88.     OldA5 := SetCurrentA5;                                { ***** Called from trap patches *****}
  89.     menuObj := FindTMenu(theMenu);
  90.     {$IFC qDebug}
  91.     IF menuObj = NIL THEN
  92.         ProgramBreak('MenuDefproc called with no TMenu object');
  93.     {$ENDC}
  94.  
  95.     { Dispatch to the TMenu object }
  96.     menuObj.HandleDefproc(message, theMenu, menuRect, hitPt, whichItem);
  97.     OldA5 := SetA5(OldA5);
  98.     END;
  99. {$Pop}
  100.  
  101. {--------------------------------------------------------------------------------------------------}
  102. {$S AInit}
  103.  
  104. PROCEDURE InitUMenu;
  105.  
  106.     TYPE
  107.         JMP                 = RECORD
  108.             opcode:             INTEGER;
  109.             address:            Ptr;
  110.             END;
  111.         JmpPtr                = ^JMP;
  112.         JmpHandle            = ^JmpPtr;
  113.  
  114.     VAR
  115.         h:                    JmpHandle;
  116.  
  117.     BEGIN
  118.     IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  119.         OpenCPort(@pMenuCPort)
  120.     ELSE
  121.         OpenPort(GrafPtr(@pMenuCPort));
  122.     pNumMenus := 0;
  123.     pMenuArray := MenuArrayHandle(NewHandle(0));
  124.     FailNIL(pMenuArray);
  125.  
  126.     h := JmpHandle(NewHandle(6));
  127.     FailNIL(h);
  128.     WITH h^^ DO
  129.         BEGIN
  130.         opcode := $4EF9;
  131.         address := @MenuDefproc;
  132.         END;
  133.     pCustDefproc := Handle(h);
  134.     END;
  135.  
  136. {--------------------------------------------------------------------------------------------------}
  137. {$S AInit}
  138.  
  139. PROCEDURE TMenu.IMenu(rsrcID: INTEGER;
  140.                       menuWidth, menuHeight: INTEGER);
  141.  
  142.     VAR
  143.         m:                    MenuHandle;
  144.         s:                    LONGINT;
  145.         p:                    LongintPtr;
  146.         i:                    INTEGER;
  147.  
  148.         r:                    Rect;
  149.         item:                INTEGER;
  150.         vp:                 VPoint;
  151.  
  152.     BEGIN
  153.     { Initialize fields }
  154.     fBorder := gZeroRect;
  155.     fMenuHandle := NIL;
  156.     vp.h := menuWidth;
  157.     vp.v := menuHeight;
  158.     IView(NIL, NIL, gZeroVPt, vp, SizeVariable, SizeVariable);
  159.  
  160.     fFlashInterval := - 1;
  161.     fNextFlash := 0;
  162.  
  163.     IF rsrcID = 0 THEN
  164.         fMenuHandle := NIL
  165.     ELSE
  166.         BEGIN
  167.         { Read in menu and set its defproc }
  168.         m := MenuHandle(GetResMenu(rsrcID));
  169.  
  170.         IF m = NIL THEN
  171.             BEGIN
  172.             {$IFC qDebug}
  173.             Writeln('rsrcID = ', rsrcID: 1);
  174.             ProgramBreak('No such MENU!');
  175.             {$ENDC}
  176.  
  177.             Free;
  178.             Failure(resNotFound, 0);
  179.             END;
  180.  
  181.         pNumMenus := pNumMenus + 1;
  182.         SetHandleSize(Handle(pMenuArray), SIZEOF(MenuRec) * pNumMenus);
  183.         WITH pMenuArray^^[pNumMenus] DO
  184.             BEGIN
  185.             mID := m^^.menuID;
  186.             mObject := SELF;
  187.             END;
  188.  
  189.         m^^.menuProc := pCustDefproc;
  190.         fMenuHandle := m;
  191.  
  192.         MenuDefproc(mSizeMsg, m, r, Point(0), item);    { recompute the menu size }
  193.         END;
  194.     END;
  195.  
  196. {--------------------------------------------------------------------------------------------------}
  197. {$S MenuNever}
  198.  
  199. FUNCTION TMenu.FindItem(hitPt: Point): INTEGER;
  200.  
  201.     BEGIN
  202.     {$IFC qDebug}
  203.     ProgramBreak('You must override TMenu.FindItem.');
  204.     {$ENDC}
  205.     END;
  206.  
  207. {--------------------------------------------------------------------------------------------------}
  208. {$S ARes}
  209.  
  210. PROCEDURE TMenu.HandleDefproc(message: INTEGER;
  211.                               theMenu: MenuHandle;
  212.                               VAR menuRect: Rect;
  213.                               hitPt: Point;
  214.                               VAR whichItem: INTEGER);
  215.  
  216.     VAR
  217.         p:                    LongintPtr;
  218.         savePort:            GrafPtr;
  219.         r:                    Rect;
  220.  
  221.     BEGIN
  222.     { Save the wmgr port & set our private port }
  223.     GetPort(savePort);
  224.  
  225.     fMenuRect := menuRect;
  226.     fHitPt := hitPt;
  227.  
  228.     IF Focus THEN
  229.         BEGIN
  230.         hitPt := fHitPt;
  231.  
  232.         ViewEnable(Odd(fMenuHandle^^.enableFlags), false {no redraw} );
  233.         CASE message OF
  234.             mDrawMsg:
  235.                 BEGIN
  236.                 {$IFC qDebug}
  237.                 IF gIntenseDebugging THEN
  238.                     Writeln('mDrawMsg');
  239.                 {$ENDC}
  240.                 HandleDrawMessage(message, theMenu, menuRect, hitPt, whichItem);
  241.                 END;
  242.  
  243.             mChooseMsg:
  244.                 BEGIN
  245.                 {$IFC qDebug}
  246.                 IF gIntenseDebugging THEN
  247.                     Writeln('mChooseMsg');
  248.                 {$ENDC}
  249.                 HandleChooseMessage(message, theMenu, menuRect, hitPt, whichItem);
  250.                 END;
  251.  
  252.             mSizeMsg:
  253.                 BEGIN
  254.                 {$IFC qDebug}
  255.                 IF gIntenseDebugging THEN
  256.                     Writeln('mSizeMsg');
  257.                 {$ENDC}
  258.                 HandleSizeMessage(message, theMenu, menuRect, hitPt, whichItem);
  259.                 END;
  260.  
  261.             mPopUpMsg:
  262.                 BEGIN
  263.                 {$IFC qDebug}
  264.                 IF gIntenseDebugging THEN
  265.                     Writeln('mPopUpMsg');
  266.                 {$ENDC}
  267.                 HandlePopUpMessage(message, theMenu, menuRect, hitPt, whichItem);
  268.                 END;
  269.             {$IFC qDebug}
  270.             OTHERWISE
  271.                 IF gIntenseDebugging THEN
  272.                     Writeln('otherwise message');
  273.             {$ENDC}
  274.         END;
  275.         InvalidateFocus;
  276.         END;
  277.  
  278.     SetPort(savePort);
  279.     END;
  280.  
  281. {--------------------------------------------------------------------------------------------------}
  282. {$S ARes}
  283.  
  284. PROCEDURE TMenu.HandleChooseMessage(message: INTEGER;
  285.                                     theMenu: MenuHandle;
  286.                                     VAR menuRect: Rect;
  287.                                     hitPt: Point;
  288.                                     VAR whichItem: INTEGER);
  289.  
  290.     VAR
  291.         newItem:            INTEGER;
  292.         hitRect:            Rect;
  293.  
  294.     BEGIN
  295.     newItem := kNoMenuItem;                             { default return }
  296.  
  297.     { See what item the user is over }
  298.  
  299.     IF IsViewEnabled THEN                                { menu enabled }
  300.         BEGIN
  301.         { see if point is within hit area }
  302.         GetQDExtent(hitRect);
  303.         AddPt(fBorder.topLeft, hitRect.topLeft);
  304.         AddPt(fBorder.botRight, hitRect.botRight);
  305.  
  306.         IF PtInRect(hitPt, hitRect) THEN                { in menu (not border) }
  307.             newItem := FindItem(hitPt);
  308.         END;
  309.  
  310.     { Update highlighting }
  311.     UpdateHighlight(whichItem, newItem);
  312.  
  313.     { Tell MenuManager about new item }
  314.     whichItem := newItem;
  315.     END;
  316.  
  317. {--------------------------------------------------------------------------------------------------}
  318. {$S ARes}
  319.  
  320. PROCEDURE TMenu.HandleDrawMessage(message: INTEGER;
  321.                                   theMenu: MenuHandle;
  322.                                   VAR menuRect: Rect;
  323.                                   hitPt: Point;
  324.                                   VAR whichItem: INTEGER);
  325.     var
  326.         extent: Rect;
  327.  
  328.     BEGIN
  329.     DrawContents;
  330.     fHighlighted := false;
  331.     if not fViewEnabled THEN
  332.         begin
  333.         PenPat(Gray);
  334.         PenMode(notSrcBic);
  335.         GetQDExtent(extent);
  336.         PaintRect(extent);
  337.         end;
  338.     END;
  339.  
  340. {--------------------------------------------------------------------------------------------------}
  341. {$S ARes}
  342.  
  343. PROCEDURE TMenu.HandleSizeMessage(message: INTEGER;
  344.                                   theMenu: MenuHandle;
  345.                                   VAR menuRect: Rect;
  346.                                   hitPt: Point;
  347.                                   VAR whichItem: INTEGER);
  348.  
  349.     VAR
  350.         vp:                 VPoint;
  351.  
  352.     BEGIN
  353.     ComputeSize(vp);
  354.     fMenuHandle^^.menuWidth := vp.h;
  355.     fMenuHandle^^.menuHeight := vp.v;
  356.     END;
  357.  
  358. {--------------------------------------------------------------------------------------------------}
  359. {$S ARes}
  360.  
  361. PROCEDURE TMenu.HandlePopUpMessage(message: INTEGER;
  362.                                    theMenu: MenuHandle;
  363.                                    VAR menuRect: Rect;
  364.                                    hitPt: Point;
  365.                                    VAR whichItem: INTEGER);
  366.  
  367.     VAR
  368.         vp:                 VPoint;
  369.  
  370.     BEGIN
  371.     {  SubPt(origin, hitPt);}
  372.  
  373.     menuRect.top := hitPt.h;
  374.     menuRect.left := hitPt.v;
  375.     ComputeSize(vp);
  376.     menuRect.bottom := menuRect.top + vp.v;
  377.     menuRect.right := menuRect.left + vp.h;
  378.     END;
  379.  
  380. {--------------------------------------------------------------------------------------------------}
  381. {$S ARes}
  382.  
  383. PROCEDURE TMenu.Highlight(whichItem: INTEGER;
  384.                           turnItOn: BOOLEAN);
  385.  
  386.     BEGIN
  387.     {$IFC qDebug}
  388.     ProgramBreak('You must override TMenu.Highlight.');
  389.     {$ENDC}
  390.     END;
  391.  
  392. {--------------------------------------------------------------------------------------------------}
  393. {$S AFields}
  394.  
  395. PROCEDURE TMenu.Fields(PROCEDURE DoToField(fieldName: Str255;
  396.                                            fieldAddr: Ptr;
  397.                                            fieldType: INTEGER)); OVERRIDE;
  398.  
  399.     BEGIN
  400.     DoToField('fFlashInterval', @fFlashInterval, bLongInt);
  401.     DoToField('fNextFlash', @fNextFlash, bLongInt);
  402.     DoToField('fHighlighted', @fHighlighted, bBoolean);
  403.     DoToField('fMenuHandle', @fMenuHandle, bHandle);
  404.     DoToField('fBorder', @fBorder, bRect);
  405.  
  406.     INHERITED Fields(DoToField);
  407.     END;
  408.  
  409. {--------------------------------------------------------------------------------------------------}
  410. {$S ARes}
  411. FUNCTION TMenu.IsItemEnabled(item:INTEGER): Boolean;
  412.  
  413.     BEGIN
  414.     IsItemEnabled := BTst(fMenuHandle^^.enableFlags, item)
  415.     END;
  416.  
  417. {--------------------------------------------------------------------------------------------------}
  418. {$S ARes}
  419.  
  420. PROCEDURE TMenu.GetMenuColors(theMenu, theItem: INTEGER; VAR theMenuColors: MenuColors);
  421.  
  422.     TYPE
  423.         TypeOfMenuInfo = (aMenuItem, aMenuTitle, aMenuBar, noType);
  424.  
  425.     VAR
  426.         aMCEntryPtr: MCEntryPtr;
  427.         typeOfRequest: TypeOfMenuInfo;
  428.         typeOfEntryFound: TypeOfMenuInfo;
  429.         theEntryMenu, theEntryItem: INTEGER;
  430.  
  431.     BEGIN
  432.     WITH theMenuColors DO
  433.         BEGIN
  434.         IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  435.             BEGIN
  436.             IF theItem <> 0 THEN
  437.                 typeOfRequest := aMenuItem
  438.             ELSE IF theMenu <> 0 THEN
  439.                 typeOfRequest := aMenuTitle
  440.             ELSE
  441.                 typeOfRequest := aMenuBar;
  442.  
  443.             theEntryMenu := theMenu;
  444.             theEntryItem := theItem;
  445.  
  446.             aMCEntryPtr := GetMCEntry(theEntryMenu, theEntryItem);
  447.             IF aMCEntryPtr = NIL THEN { not found, try as title }
  448.                 BEGIN
  449.                 theEntryItem := 0;
  450.                 aMCEntryPtr := GetMCEntry(theEntryMenu, theEntryItem);
  451.                 IF aMCEntryPtr = NIL THEN { not found, try as menubar }
  452.                     BEGIN
  453.                     theEntryMenu := 0;
  454.                     aMCEntryPtr := GetMCEntry(theEntryMenu, theEntryItem);
  455.                     END;
  456.                 END;
  457.  
  458.             IF aMCEntryPtr = NIL THEN
  459.                 typeOfEntryFound := noType
  460.             ELSE
  461.                 BEGIN
  462.                 IF theEntryItem <> 0 THEN
  463.                     typeOfEntryFound := aMenuItem
  464.                 ELSE IF theEntryMenu <> 0 THEN
  465.                     typeOfEntryFound := aMenuTitle
  466.                 ELSE
  467.                     typeOfEntryFound := aMenuBar;
  468.                 END;
  469.  
  470.             CASE typeOfEntryFound OF
  471.                 aMenuItem:
  472.                     WITH aMCEntryPtr^ DO
  473.                         BEGIN
  474.                         itemColor := mctRGB1;
  475.                         backgroundColor := mctRGB4;
  476.                         markColor := mctRGB1;
  477.                         commandColor := mctRGB1;
  478.                         END;
  479.                 aMenuTitle:
  480.                     CASE typeOfRequest OF
  481.                         aMenuItem:
  482.                             WITH aMCEntryPtr^ DO
  483.                                 BEGIN
  484.                                 itemColor := mctRGB3;
  485.                                 backgroundColor := mctRGB4;
  486.                                 markColor := mctRGB3;
  487.                                 commandColor := mctRGB3;
  488.                                 END;
  489.                         aMenuTitle:
  490.                             WITH aMCEntryPtr^ DO
  491.                                 BEGIN
  492.                                 itemColor := mctRGB1;
  493.                                 backgroundColor := mctRGB2;
  494.                                 markColor := mctRGB1;
  495.                                 commandColor := mctRGB1;
  496.                                 END;
  497.                     END;
  498.                 aMenuBar:
  499.                     CASE typeOfRequest OF
  500.                         aMenuItem:
  501.                             WITH aMCEntryPtr^ DO
  502.                                 BEGIN
  503.                                 itemColor := mctRGB3;
  504.                                 backgroundColor := mctRGB2;
  505.                                 markColor := mctRGB3;
  506.                                 commandColor := mctRGB3;
  507.                                 END;
  508.                         aMenuTitle:
  509.                             WITH aMCEntryPtr^ DO
  510.                                 BEGIN
  511.                                 itemColor := mctRGB1;
  512.                                 backgroundColor := mctRGB4;
  513.                                 markColor := mctRGB1;
  514.                                 commandColor := mctRGB1;
  515.                                 END;
  516.                         aMenuBar:
  517.                             WITH aMCEntryPtr^ DO
  518.                                 BEGIN
  519.                                 itemColor := mctRGB1;
  520.                                 backgroundColor := mctRGB4;
  521.                                 markColor := mctRGB1;
  522.                                 commandColor := mctRGB1;
  523.                                 END;
  524.                     END;
  525.                 noType:
  526.                     BEGIN
  527.                     itemColor := gRGBBlack;
  528.                     backgroundColor := gRGBWhite;
  529.                     markColor := gRGBBlack;
  530.                     commandColor := gRGBBlack;
  531.                     END;
  532.             END;
  533.             END
  534.         ELSE
  535.             BEGIN
  536.             itemColor := gRGBBlack;
  537.             backgroundColor := gRGBWhite;
  538.             markColor := gRGBBlack;
  539.             commandColor := gRGBBlack;
  540.             END;
  541.         END;
  542.     END;
  543.  
  544. {--------------------------------------------------------------------------------------------------}
  545. {$S ARes}
  546.  
  547. PROCEDURE TMenu.UpdateHighlight(oldItem, newItem: INTEGER);
  548.  
  549.     BEGIN
  550.     { Update highlighting }
  551.     IF newItem <> oldItem THEN
  552.         BEGIN
  553.         IF fHighlighted THEN
  554.             IF oldItem <> kNoMenuItem THEN
  555.                 Highlight(oldItem, false);
  556.  
  557.         fHighlighted := newItem <> kNoMenuItem;
  558.         IF fHighlighted THEN
  559.             Highlight(newItem, TRUE);
  560.  
  561.         IF fFlashInterval >= 0 THEN
  562.             fNextFlash := Future(fFlashInterval);
  563.         END
  564.  
  565.     ELSE IF fFlashInterval >= 0 THEN
  566.         IF TickCount > fNextFlash THEN
  567.             BEGIN
  568.             fHighlighted := NOT fHighlighted;
  569.             Highlight(oldItem, fHighlighted);
  570.             fNextFlash := Future(fFlashInterval);
  571.             END;
  572.     END;
  573.  
  574. {--------------------------------------------------------------------------------------------------}
  575. {$S ARes}
  576.  
  577. FUNCTION TMenu.Focus: BOOLEAN; OVERRIDE;
  578.  
  579.     VAR
  580.         r:                    Rect;
  581.         vorigin:            VPoint;
  582.         origin:             Point;
  583.         {$IFC qDebug}
  584.         currentPort:        GrafPtr;
  585.         {$ENDC}
  586.         theMenuColors:        MenuColors;
  587.  
  588.     BEGIN
  589.     IF IsFocused THEN
  590.         BEGIN
  591.         {$IFC FALSE}
  592.         IF LONGINT(pMenuCPort.portRect.topLeft) <> 0 THEN
  593.             ProgramBreak('TMenu.Focus: Origin is not (0,0)');
  594.  
  595.         GetPort(currentPort);
  596.         IF currentPort <> @pMenuCPort THEN
  597.             ProgramBreak('TMenu.Focus: Port is incorrect');
  598.         {$ENDC}
  599.         END
  600.     ELSE                                                {IF @pMenuCPort <> NIL THEN}
  601.         BEGIN
  602.         IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  603.             InitCPort(@pMenuCPort)
  604.         ELSE
  605.             InitPort(GrafPtr(@pMenuCPort));             { set the port to default settings }
  606.  
  607.         SetPort(@pMenuCPort);
  608.         gLongOffset := gZeroVPt;
  609.  
  610.  
  611.  
  612.         { Try to make the best match for the menu colors without requiring programmer intervention.
  613.         by setting the color environment to be for items. }
  614.  
  615.         GetMenuColors(fMenuHandle^^.menuID, 1, theMenuColors);
  616.         SetIfColor(theMenuColors.itemColor);
  617.         SetIfBkColor(theMenuColors.backgroundColor);
  618.  
  619.         { Change the origin so that drawing is relative to fLocation }
  620.         {$Push}{$H-}
  621.         origin := VPtToPt(fLocation);
  622.         {$Pop}
  623.  
  624.         SubPt(fMenuRect.topLeft, origin);
  625.         SetOrigin(origin.h, origin.v);
  626.  
  627.         {$Push}{$H-}
  628.         AddPt(origin, fHitPt);
  629.         OffsetRect(fMenuRect, origin.h, origin.v);
  630.         ClipRect(fMenuRect);
  631.         {$Pop}
  632.         gFocusedView := SELF;
  633.         END;
  634.     Focus := TRUE;
  635.     END;
  636.  
  637. {--------------------------------------------------------------------------------------------------}
  638. {$S ARes}
  639.  
  640. FUNCTION TMenu.FocusOnSuperView: BOOLEAN; OVERRIDE;
  641.  
  642.     BEGIN
  643.     FocusOnSuperView := false;
  644.     END;
  645.  
  646. {--------------------------------------------------------------------------------------------------}
  647. {$S ARes}
  648.  
  649. FUNCTION TMenu.GetGrafPort: GrafPtr; OVERRIDE;
  650.  
  651.     BEGIN
  652.     GetGrafPort := GrafPtr(@pMenuCPort);
  653.     END;
  654.